package tm.testing;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;

import com.jme.bounding.BoundingSphere;
import com.jme.curve.CatmullRomCurve;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Spatial;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;

public class Road extends Track {
	
	//SOME CONSTANTS FOR TRACKPIECE TYPIFICATION
	public static int NONCHAINED		= 0;
	public static int STRAIGHT_HEADINGX	= 1;
	public static int STRAIGHT_HEADINGY	= 2;
	public static int CURVE_ROTATE0		= 3;
	public static int CURVE_ROTATE90	= 4;
	public static int CURVE_ROTATE180	= 5;
	public static int CURVE_ROTATE270	= 6;
	public static int FULLCROSSING		= 7;
	public static int TRIPLE_RIGHT		= 8;
	public static int TRIPLE_BOTTOM		= 9;
	public static int TRIPLE_LEFT		= 10;
	public static int TRIPLE_TOP		= 11;
	
	public static int RIGHT 	= 0;
	public static int TOWARDS 	= 1;
	
	
	
	public Road(String id, MapGrid mg) {
		super(id, mg);
		// TODO Auto-generated constructor stub
	}

	
	
	public void addField(Coordinate c) {
		if(!containsCoordinate(c)) {
			track.add(c);
		} else {
			// TODO give some feedback
			//System.out.println("DOUBLE ENTRY: P("+c.getX()+"|"+c.getY()+")");
		}
	}
	
	
	public void addUpdateField(Coordinate c) {
		if(!containsCoordinate(c)) {
			removeAffectedGeometry(c);
			track.add(c);
			updateSpatials(c);
			showAffectedGeometry(c);
		} else {
			// TODO give some feedback
			//System.out.println("DOUBLE ENTRY: P("+c.getX()+"|"+c.getY()+")");
		}
	}
	
	public void removeUpdateField(Coordinate c) {
		if(containsCoordinate(c)) {
			removeAffectedGeometry(c);
			removeField(c);
			updateSpatials(c);
			showRemovalAffectedGeometry(c);
		} else {
			// TODO give some feedback
			//System.out.println("NO SUCH ENTRY: P("+c.getX()+"|"+c.getY()+")");
		}
	}
	
	
	
	public void computeSpatials() {
		try {
			for(int i=0; i<track.size(); i++) {
				Coordinate now = track.get(i);
				//compute the 4 surrounding fields
				Coordinate top 		= null;
				Coordinate right 	= null;
				Coordinate left 	= null;
				Coordinate bottom	= null;
				//compute top
				top = new Coordinate(now.getX(),now.getY()+1);
				if(!mapGrid.isValidCoordinate(top)) {
					top = null;
				} else if(!containsCoordinate(top)) {
					top = null;
				}
				//compute right
				right = new Coordinate(now.getX()+1,now.getY());
				if(!mapGrid.isValidCoordinate(right)) {
					right = null;
				} else if(!containsCoordinate(right)) {
					right = null;
				}
				//compute left
				left = new Coordinate(now.getX()-1,now.getY());
				if(!mapGrid.isValidCoordinate(left)) {
					left = null;
				} else if(!containsCoordinate(left)) {
					left = null;
				}
				//compute bottom
				bottom = new Coordinate(now.getX(),now.getY()-1);
				if(!mapGrid.isValidCoordinate(bottom)) {
					bottom = null;
				} else if (!containsCoordinate(bottom)) {
					bottom = null;
				}

				//Create tmp spatial:
				Spatial tmp;
				

				//NOT CONNECTED ------------------------------------------------------------------------------------------------------------
				//Single, nonchained and lonesome road element
				if(top==null && right==null && left==null && bottom==null) {
					// TODO Add some lonesome element ;)
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),NONCHAINED);
					spatials.add(tmp);
					track.get(i).setName("T_"+NONCHAINED);
					ref.put(track.get(i), tmp);
				}
				//--------------------------------------------------------------------------------------------------------------------------

				//SINGLE CONNECTED ---------------------------------------------------------------------------------------------------------
				//Only connected to the top, nothing to do
				if(top!=null && right==null && left==null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGX);
					spatials.add(tmp);
					track.get(i).setName("T_"+STRAIGHT_HEADINGX);
					ref.put(track.get(i), tmp);
				}							
				//Only connected to the right, simply turn around 90 degree
				if(top==null && right!=null && left==null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGY);
					spatials.add(tmp);
					track.get(i).setName("T_"+STRAIGHT_HEADINGY);
					ref.put(track.get(i), tmp);
				}
				//Only connected to the left, simply turn around 90 degree
				if(top==null && right==null && left!=null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGY);
					spatials.add(tmp);		
					track.get(i).setName("T_"+STRAIGHT_HEADINGY);
					ref.put(track.get(i), tmp);
				}
				//Only connected to the bottom, nothing to do
				if(top==null && right==null && left==null && bottom!=null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGX);
					spatials.add(tmp);
					track.get(i).setName("T_"+STRAIGHT_HEADINGX);
					ref.put(track.get(i), tmp);
				}
				//--------------------------------------------------------------------------------------------------------------------------
				
				//DOUBLE CONNECTED ---------------------------------------------------------------------------------------------------------
				//Connected top and right, curve 
				if(top!=null && right!=null && left==null && bottom==null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE90);
					spatials.add(tmp);
					track.get(i).setName("T_"+CURVE_ROTATE90);
					ref.put(track.get(i), tmp);
				}
				//Connected right and bottom, curve 
				if(top==null && right!=null && left==null && bottom!=null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE0);
					spatials.add(tmp);
					track.get(i).setName("T_"+CURVE_ROTATE0);
					ref.put(track.get(i), tmp);
				}
				//Connected bottom and left, curve 
				if(top==null && right==null && left!=null && bottom!=null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE270);
					spatials.add(tmp);		
					track.get(i).setName("T_"+CURVE_ROTATE270);
					ref.put(track.get(i), tmp);
				}
				//Connected left and top, curve 
				if(top!=null && right==null && left!=null && bottom==null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE180);
					spatials.add(tmp);
					track.get(i).setName("T_"+CURVE_ROTATE180);
					ref.put(track.get(i), tmp);
				}
				//Connected top and bottom, curve 
				if(top!=null && right==null && left==null && bottom!=null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGX);
					spatials.add(tmp);	
					track.get(i).setName("T_"+STRAIGHT_HEADINGX);
					ref.put(track.get(i), tmp);
				}
				//Connected left and right, curve 
				if(top==null && right!=null && left!=null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGY);
					spatials.add(tmp);	
					track.get(i).setName("T_"+STRAIGHT_HEADINGY);
					ref.put(track.get(i), tmp);	
				}
				//--------------------------------------------------------------------------------------------------------------------------

				//TRIPLE CONNECTED ---------------------------------------------------------------------------------------------------------
				//Connected top, right, bottom triple
				if(top!=null && right!=null && left==null && bottom!=null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_RIGHT);
					spatials.add(tmp);
					track.get(i).setName("T_"+TRIPLE_RIGHT);
					ref.put(track.get(i), tmp);	
				}
				//Connected right, bottom, left triple
				if(top==null && right!=null && left!=null && bottom!=null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_BOTTOM);
					spatials.add(tmp);
					track.get(i).setName("T_"+TRIPLE_BOTTOM);
					ref.put(track.get(i), tmp);	
				}
				//Connected bottom, left, top triple
				if(top!=null && right==null && left!=null && bottom!=null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_LEFT);
					spatials.add(tmp);
					track.get(i).setName("T_"+TRIPLE_LEFT);
					ref.put(track.get(i), tmp);	
				}
				//Connected left, top, right triple
				if(top!=null && right!=null && left!=null && bottom==null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_TOP);
					spatials.add(tmp);	
					track.get(i).setName("T_"+TRIPLE_TOP);
					ref.put(track.get(i), tmp);	
				}
				//--------------------------------------------------------------------------------------------------------------------------

				//ALL CONNECTED ------------------------------------------------------------------------------------------------------------
				//all connected, crossing
				if(top!=null && right!=null && left!=null && bottom!=null) {
					tmp = getCrossingSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f));
					spatials.add(tmp);
					track.get(i).setName("T_"+FULLCROSSING);
					ref.put(track.get(i), tmp);
				}
				//--------------------------------------------------------------------------------------------------------------------------
			}
			
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void updateSpatials(Coordinate c) {
		try {
			// TODO Compute only the 5 affected spatials, but might be much code as
			//		we can't use the for-loop and have to use the code 5 times instead...
			
			// Up to now, clear all spatials:
			clearSpatials();
			
			
			//Calculate new ones:
			
			for(int i=0; i<track.size(); i++) {
				Coordinate now = track.get(i);
				//compute the 4 surrounding fields
				Coordinate top 		= null;
				Coordinate right 	= null;
				Coordinate left 	= null;
				Coordinate bottom	= null;
				//compute top
				top = new Coordinate(now.getX(),now.getY()+1);
				if(!mapGrid.isValidCoordinate(top)) {
					top = null;
				} else if(!containsCoordinate(top)) {
					top = null;
				}
				//compute right
				right = new Coordinate(now.getX()+1,now.getY());
				if(!mapGrid.isValidCoordinate(right)) {
					right = null;
				} else if(!containsCoordinate(right)) {
					right = null;
				}
				//compute left
				left = new Coordinate(now.getX()-1,now.getY());
				if(!mapGrid.isValidCoordinate(left)) {
					left = null;
				} else if(!containsCoordinate(left)) {
					left = null;
				}
				//compute bottom
				bottom = new Coordinate(now.getX(),now.getY()-1);
				if(!mapGrid.isValidCoordinate(bottom)) {
					bottom = null;
				} else if (!containsCoordinate(bottom)) {
					bottom = null;
				}

				
				//Create tmp spatial:
				Spatial tmp;
				

				//NOT CONNECTED ------------------------------------------------------------------------------------------------------------
				//Single, nonchained and lonesome road element
				if(top==null && right==null && left==null && bottom==null) {
					// TODO Add some lonesome element ;)
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),NONCHAINED);
					spatials.add(tmp);
					track.get(i).setName("T_"+NONCHAINED);
					ref.put(track.get(i), tmp);
				}
				//--------------------------------------------------------------------------------------------------------------------------

				//SINGLE CONNECTED ---------------------------------------------------------------------------------------------------------
				//Only connected to the top, nothing to do
				if(top!=null && right==null && left==null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGX);
					spatials.add(tmp);
					track.get(i).setName("T_"+STRAIGHT_HEADINGX);
					ref.put(track.get(i), tmp);
				}							
				//Only connected to the right, simply turn around 90 degree
				if(top==null && right!=null && left==null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGY);
					spatials.add(tmp);
					track.get(i).setName("T_"+STRAIGHT_HEADINGY);
					ref.put(track.get(i), tmp);
				}
				//Only connected to the left, simply turn around 90 degree
				if(top==null && right==null && left!=null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGY);
					spatials.add(tmp);		
					track.get(i).setName("T_"+STRAIGHT_HEADINGY);
					ref.put(track.get(i), tmp);
				}
				//Only connected to the bottom, nothing to do
				if(top==null && right==null && left==null && bottom!=null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGX);
					spatials.add(tmp);
					track.get(i).setName("T_"+STRAIGHT_HEADINGX);
					ref.put(track.get(i), tmp);
				}
				//--------------------------------------------------------------------------------------------------------------------------
				
				//DOUBLE CONNECTED ---------------------------------------------------------------------------------------------------------
				//Connected top and right, curve 
				if(top!=null && right!=null && left==null && bottom==null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE90);
					spatials.add(tmp);
					track.get(i).setName("T_"+CURVE_ROTATE90);
					ref.put(track.get(i), tmp);
				}
				//Connected right and bottom, curve 
				if(top==null && right!=null && left==null && bottom!=null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE0);
					spatials.add(tmp);
					track.get(i).setName("T_"+CURVE_ROTATE0);
					ref.put(track.get(i), tmp);
				}
				//Connected bottom and left, curve 
				if(top==null && right==null && left!=null && bottom!=null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE270);
					spatials.add(tmp);		
					track.get(i).setName("T_"+CURVE_ROTATE270);
					ref.put(track.get(i), tmp);
				}
				//Connected left and top, curve 
				if(top!=null && right==null && left!=null && bottom==null) {
					tmp = getCurveSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),CURVE_ROTATE180);
					spatials.add(tmp);
					track.get(i).setName("T_"+CURVE_ROTATE180);
					ref.put(track.get(i), tmp);
				}
				//Connected top and bottom, curve 
				if(top!=null && right==null && left==null && bottom!=null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGX);
					spatials.add(tmp);	
					track.get(i).setName("T_"+STRAIGHT_HEADINGX);
					ref.put(track.get(i), tmp);
				}
				//Connected left and right, curve 
				if(top==null && right!=null && left!=null && bottom==null) {
					tmp = getStraightSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),STRAIGHT_HEADINGY);
					spatials.add(tmp);	
					track.get(i).setName("T_"+STRAIGHT_HEADINGY);
					ref.put(track.get(i), tmp);	
				}
				//--------------------------------------------------------------------------------------------------------------------------

				//TRIPLE CONNECTED ---------------------------------------------------------------------------------------------------------
				//Connected top, right, bottom triple
				if(top!=null && right!=null && left==null && bottom!=null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_RIGHT);
					spatials.add(tmp);
					track.get(i).setName("T_"+TRIPLE_RIGHT);
					ref.put(track.get(i), tmp);	
				}
				//Connected right, bottom, left triple
				if(top==null && right!=null && left!=null && bottom!=null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_BOTTOM);
					spatials.add(tmp);
					track.get(i).setName("T_"+TRIPLE_BOTTOM);
					ref.put(track.get(i), tmp);	
				}
				//Connected bottom, left, top triple
				if(top!=null && right==null && left!=null && bottom!=null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_LEFT);
					spatials.add(tmp);
					track.get(i).setName("T_"+TRIPLE_LEFT);
					ref.put(track.get(i), tmp);	
				}
				//Connected left, top, right triple
				if(top!=null && right!=null && left!=null && bottom==null) {
					tmp = getTripleSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f),TRIPLE_TOP);
					spatials.add(tmp);	
					track.get(i).setName("T_"+TRIPLE_TOP);
					ref.put(track.get(i), tmp);	
				}
				//--------------------------------------------------------------------------------------------------------------------------

				//ALL CONNECTED ------------------------------------------------------------------------------------------------------------
				//all connected, crossing
				if(top!=null && right!=null && left!=null && bottom!=null) {
					tmp = getCrossingSpatial(mapGrid.getElementCoord(track.get(i).getX(), track.get(i).getY(), 127.0f));
					spatials.add(tmp);
					track.get(i).setName("T_"+FULLCROSSING);
					ref.put(track.get(i), tmp);
				}
				//--------------------------------------------------------------------------------------------------------------------------
			}
			
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public boolean containsCoordinate(Coordinate c) {
		Iterator<Coordinate> itr = track.iterator();
		while(itr.hasNext()) {
			Coordinate tmp = itr.next();
			if(tmp.getX()==c.getX() && tmp.getY()==c.getY()) {
				return true;
			}
		}
		return false;
	}
	
	public String getTrackPieceType(Coordinate c) {
		Iterator<Coordinate> itr = track.iterator();
		while(itr.hasNext()) {
			Coordinate tmp = itr.next();
			if(tmp.getX()==c.getX() && tmp.getY()==c.getY()) {
				return tmp.getName();
			}
		}
		return null;
	}
	
	public void showGeometry() {
		for(int i=0; i<track.size(); i++) {
				try {
					mapGrid.getGridElement(track.get(i).getX(), track.get(i).getY()).addTrackPiece(spatials.get(i));
				} catch (MapElementIndexOutOfBoundsException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
	
	private void showAffectedGeometry(Coordinate c) {
		try {
			if(ref.containsKey(c)) {
				mapGrid.getGridElement(c.getX(), c.getY()).addTrackPiece(getSpatialByCoordinate(c));
				mapGrid.getGridElement(c.getX(), c.getY()+1).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX(), c.getY()+1)));
				mapGrid.getGridElement(c.getX()+1, c.getY()).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX()+1, c.getY())));
				mapGrid.getGridElement(c.getX(), c.getY()-1).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX(), c.getY()-1)));
				mapGrid.getGridElement(c.getX()-1, c.getY()).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX()-1, c.getY())));
			}
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto generated catch block
			e.printStackTrace();
		}
	}
	
	private void showRemovalAffectedGeometry(Coordinate c) {
		try {
			mapGrid.getGridElement(c.getX(), c.getY()+1).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX(), c.getY()+1)));
			mapGrid.getGridElement(c.getX()+1, c.getY()).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX()+1, c.getY())));
			mapGrid.getGridElement(c.getX(), c.getY()-1).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX(), c.getY()-1)));
			mapGrid.getGridElement(c.getX()-1, c.getY()).addTrackPiece(getSpatialByCoordinate(new Coordinate(c.getX()-1, c.getY())));
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto generated catch block
			e.printStackTrace();
		}		
	}
	
	private void removeAffectedGeometry(Coordinate c) {
		try {
			mapGrid.getGridElement(c.getX(), c.getY()).removeTrackPiece();
			mapGrid.getGridElement(c.getX(), c.getY()+1).removeTrackPiece();
			mapGrid.getGridElement(c.getX()+1, c.getY()).removeTrackPiece();
			mapGrid.getGridElement(c.getX(), c.getY()-1).removeTrackPiece();
			mapGrid.getGridElement(c.getX()-1, c.getY()).removeTrackPiece();
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated so-called "scheißdreck"
			e.printStackTrace();
		}
	}

	private Spatial getStraightSpatial(Vector3f v, int type) {
	      URL model=Road.class.getClassLoader().getResource("data/models/road_straight.obj");

	      // Create something to convert .obj format to .jme
	      FormatConverter converter=new ObjToJme();
	      // Point the converter to where it will find the .mtl file from
	      converter.setProperty("mtllib",model);

	      // This byte array will hold my .jme file
	      ByteArrayOutputStream BO=new ByteArrayOutputStream();

	      // Use the format converter to convert .obj to .jme
	     try {
	    	  converter.convert(model.openStream(), BO);
	    	  Spatial maggie;
	    	  maggie = (Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
		      maggie.setName("T_"+type);
		      maggie.setModelBound(new BoundingSphere());
		      maggie.updateModelBound();
		      maggie.setLocalScale(1);
		      if(type == STRAIGHT_HEADINGY) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI/2 , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      maggie.setLocalTranslation(v);
		      maggie.updateRenderState();
		      return maggie;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	private Spatial getCurveSpatial(Vector3f v, int type) {
	      URL model=Road.class.getClassLoader().getResource("data/models/road_curve.obj");

	      // Create something to convert .obj format to .jme
	      FormatConverter converter=new ObjToJme();
	      // Point the converter to where it will find the .mtl file from
	      converter.setProperty("mtllib",model);

	      // This byte array will hold my .jme file
	      ByteArrayOutputStream BO=new ByteArrayOutputStream();

	      // Use the format converter to convert .obj to .jme
	     try {
	    	  converter.convert(model.openStream(), BO);
	    	  Spatial maggie;
	    	  maggie = (Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
		      maggie.setName("T_"+type);
		      maggie.setModelBound(new BoundingSphere());
		      maggie.updateModelBound();
		      maggie.setLocalScale(1);
		      if(type == CURVE_ROTATE270) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI/2 , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      if(type == CURVE_ROTATE0) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      if(type == CURVE_ROTATE90) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI * 3 / 2 , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      maggie.setLocalTranslation(v);
		      maggie.updateRenderState();
		      return maggie;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	private Spatial getTripleSpatial(Vector3f v, int type) {
	      URL model=Road.class.getClassLoader().getResource("data/models/road_triple.obj");

	      // Create something to convert .obj format to .jme
	      FormatConverter converter=new ObjToJme();
	      // Point the converter to where it will find the .mtl file from
	      converter.setProperty("mtllib",model);

	      // This byte array will hold my .jme file
	      ByteArrayOutputStream BO=new ByteArrayOutputStream();

	      // Use the format converter to convert .obj to .jme
	     try {
	    	  converter.convert(model.openStream(), BO);
	    	  Spatial maggie;
	    	  maggie = (Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
		      maggie.setName("T_"+type);
		      maggie.setModelBound(new BoundingSphere());
		      maggie.updateModelBound();
		      maggie.setLocalScale(1);
		      if(type == TRIPLE_BOTTOM) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI/2 , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      if(type == TRIPLE_RIGHT) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      if(type == TRIPLE_TOP) {
			      Quaternion rotate90 = new Quaternion();
			      rotate90.fromAngleAxis( FastMath.PI * 3 / 2 , new Vector3f(0,1,0) );
			      maggie.setLocalRotation(rotate90);
		      }
		      maggie.setLocalTranslation(v);
		      maggie.updateRenderState();
		      return maggie;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	private Spatial getCrossingSpatial(Vector3f v) {
	      URL model=Road.class.getClassLoader().getResource("data/models/road_crossing.obj");

	      // Create something to convert .obj format to .jme
	      FormatConverter converter=new ObjToJme();
	      // Point the converter to where it will find the .mtl file from
	      converter.setProperty("mtllib",model);

	      // This byte array will hold my .jme file
	      ByteArrayOutputStream BO=new ByteArrayOutputStream();

	      // Use the format converter to convert .obj to .jme
	     try {
	    	  converter.convert(model.openStream(), BO);
	    	  Spatial maggie;
	    	  maggie = (Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
		      maggie.setName("T_"+FULLCROSSING);
		      maggie.setModelBound(new BoundingSphere());
		      maggie.updateModelBound();
		      maggie.setLocalScale(1);
		      maggie.setLocalTranslation(v);
		      maggie.updateRenderState();
		      return maggie;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	public Quaternion getOrientation(Coordinate c) throws MapElementIndexOutOfBoundsException {
		return mapGrid.getGridElement(c.getX(), c.getY()).getTrackPiece().getWorldRotation();
	}
	
	public ArrayList<Vector3f> getCurvePoints(Coordinate c, int orientation) throws MapElementIndexOutOfBoundsException {
		// TODO throw some exception if coordinate isn't within this road or something like that
		ArrayList<Vector3f> res = new ArrayList<Vector3f>();
		if(containsCoordinate(c)) {
			//----STRAIGHT HEADINGX------------------------------------------------------------------------------------------------------------
			if(getTrackPieceType(c).equals("T_"+STRAIGHT_HEADINGX)) {
				Vector3f result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setX(result.getX()+13);
				} else if (orientation==TOWARDS) {
					result.setX(result.getX()-13);
				}
				result.setZ(result.getZ()+40);	
				res.add(result);
				result = new Vector3f(result);
				result.setZ(result.getZ()-80);
				res.add(result);
			//---------------------------------------------------------------------------------------------------------------------------------	
				
			//----STRAIGHT HEADINGY------------------------------------------------------------------------------------------------------------
			} else if(getTrackPieceType(c).equals("T_"+STRAIGHT_HEADINGY)) {
				Vector3f result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setZ(result.getZ()+13);
				} else if (orientation==TOWARDS) {
					result.setZ(result.getZ()-13);
				}
				result.setX(result.getX()-40);
				res.add(result);
				result = new Vector3f(result);
				result.setX(result.getX()+80);
				res.add(result);
			//---------------------------------------------------------------------------------------------------------------------------------	

				
			//----CURVE ROTATE180--------------------------------------------------------------------------------------------------------------
			} else if(getTrackPieceType(c).equals("T_"+CURVE_ROTATE180)) {
				
				//End Point
				Vector3f result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setZ(result.getZ()+13);
				} else if (orientation==TOWARDS) {
					result.setZ(result.getZ()-13);
				}
				result.setX(result.getX()-40);
				res.add(result);
				//Past-mid Point
				result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setZ(result.getZ()+12);
					result.setX(result.getX()-20);
				} else if (orientation==TOWARDS) {
					result.setZ(result.getZ()-15);
					result.setX(result.getX()-30);
				};
				res.add(result);
				//Mid Point
				result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setZ(result.getZ()+0);
					result.setX(result.getX()+0);
				} else if (orientation==TOWARDS) {
					result.setZ(result.getZ()-20);
					result.setX(result.getX()-20);
				};
				res.add(result);
				//Pre-mid Point
				result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setZ(result.getZ()-20);
					result.setX(result.getX()+12);
				} else if (orientation==TOWARDS) {
					result.setZ(result.getZ()-30);
					result.setX(result.getX()-15);
				};
				res.add(result);
				//Start Point
				result = mapGrid.getElementCoord(c.getX(), c.getY(), 127.5f);
				if(orientation==RIGHT) {
					result.setX(result.getX()+13);
				} else if (orientation==TOWARDS) {
					result.setX(result.getX()-13);
				}
				result.setZ(result.getZ()-40);
				res.add(result);

				//Based on this 5 points we create a CatmullRomCurve and use their points
				CatmullRomCurve cr = new CatmullRomCurve("tmpl", res.toArray(new Vector3f[0]));
				res = new ArrayList<Vector3f>();
				float pos = 0;
				for(int i=0; i<=20; i++) {
					res.add(cr.getPoint(pos));
					pos += 0.05f;
				}
			//---------------------------------------------------------------------------------------------------------------------------------	

			}
		}
		return res;
	}
	
}